package com.ruibang.glass.common.utils;

import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.*;

public class HttpUtils {
    /**
     * Http timeouts
     */
    public static final int DEFAULT_HTTP_CONNECTION_TIMEOUT = 100 * 1000;
    public static final int DEFAULT_HTTP_READ_TIMEOUT = 100 * 1000;
    /**
     * Http connections
     */
    public static final int DEFAULT_MAX_PER_ROUTE = 20;
    public static final int MAX_TOTAL = 200;

    public static final String CHARSET_UTF8 = "UTF-8";
    private static final CloseableHttpClient httpClient = getHttpClient();

    public enum ContentType {

        WILDCARD("*/*"),
        APPLICATION_XML("application/xml"),
        APPLICATION_ATOM_XML("application/atom+xml"),
        APPLICATION_XHTML_XML("application/xhtml+xml"),
        APPLICATION_SVG_XML("application/svg+xml"),
        APPLICATION_JSON("application/json"),
        APPLICATION_FORM_URLENCODED("application/x-www-form-urlencoded"),
        MULTIPART_FORM_DATA("multipart/form-data"),
        APPLICATION_OCTET_STREAM("application/octet-stream");

        private String name;

        private ContentType(String name) {
            this.name = name;
        }

        public String value() {
            return this.name;
        }
    }

    /**
     * 绕过验证 (公共方法)
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static SSLContext createIgnoreVerifySSL() {
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSLv3");
            // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
            X509TrustManager trustManager = new X509TrustManager() {
                public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
                }

                public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
                }

                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            sc.init(null, new TrustManager[]{trustManager}, null);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sc;
    }

    /**
     * 适合多线程的HttpClient (公共方法)
     *
     * @return CloseableHttpClient
     */
    public static CloseableHttpClient getHttpClient() {
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(createIgnoreVerifySSL()))
                .build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        // 设置连接池大小
        connManager.setMaxTotal(MAX_TOTAL);
        connManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(DEFAULT_HTTP_CONNECTION_TIMEOUT)
                .setSocketTimeout(DEFAULT_HTTP_READ_TIMEOUT)
                .build();
        return HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig).build();
    }

    /**
     * 执行 一个 带有基础认证的 请求 (公共方法)
     *
     * @param request
     * @param userName
     * @param userPass
     * @return
     */
    public static HttpResponse getBasicAuthortion(HttpUriRequest request, String userName, String userPass) {
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userName, userPass);

        Header header = null;

        try {

            header = new BasicScheme().authenticate(credentials, request);

        } catch (AuthenticationException e) {

            e.printStackTrace();

        }

        request.addHeader(header);

        HttpResponse response = null;

        try {

            response = httpClient.execute(request);

        } catch (IOException e) {

            e.printStackTrace();

        }
        return response;

    }

    /**
     * POST 方法请求
     *
     * @param url
     * @param text
     * @param contentType
     * @param header
     * @return
     */
    public static String doPost(String url, String text, ContentType contentType, Header... header) {
        String result = null;
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity myEntity = new StringEntity(text, CHARSET_UTF8);
            if (header != null) {
                for (int i = 0; i < header.length; i++) {
                    httpPost.addHeader(header[i]);
                }
            }
            if (contentType != null) {
                httpPost.addHeader("Content-Type", contentType.value());
            }
            httpPost.setEntity(myEntity);
            response = httpClient.execute(httpPost);
            return EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

//    public ResultBody<String> responseToResultBody(HttpResponse httpResponse){
//        int statusCode = httpResponse.getStatusLine().getStatusCode();
//
//    }

    public static String doGet(String url, Header... headers) throws IOException {
        CloseableHttpResponse response = null;
        HttpGet httpGet = new HttpGet(url);
        String result = "";
        if (headers != null) {
            for (int i = 0; i < headers.length; i++) {
                httpGet.addHeader(headers[i]);
            }
        }
        response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            result = IOUtils.toString(entity.getContent(), CHARSET_UTF8);
        }
        return result;
    }

    /**
     * post from表单
     *
     * @param url
     * @param param
     * @return
     */
    public static String doPost(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.name);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (Optional.ofNullable(response).isPresent()) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    public static String doPostJson(String url, String body) {
        // 创建Httpclient对象
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", ContentType.APPLICATION_JSON.name);
            // 创建参数列表
            httpPost.setEntity(new StringEntity(body, "UTF-8"));
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (Optional.ofNullable(response).isPresent()) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    public static String doPostFrom(String url, Map<String, String> param, Header... headers) {
        // 创建Httpclient对象
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.name);
            if (headers != null) {
                for (int i = 0; i < headers.length; i++) {
                    httpPost.addHeader(headers[i]);
                }
            }
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (Optional.ofNullable(response).isPresent()) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }


    /**
     * get 请求
     *
     * @param url
     * @param param
     * @return
     */
    public static String get(String url, Map<String, String> param) {
        // 创建Httpclient对象
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
            // 执行请求
            response = httpClient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (Optional.ofNullable(response).isPresent()) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }


    /**
     * 将url和map数据封装成url携带的参数
     *
     * @param map 要传输的数据
     * @return 携带参数的url
     */
    private static String mapToUrlString(String url, Map<String, Object> map) {
        StringBuffer sb = null;
        if (map != null && map.size() > 0) {
            sb = new StringBuffer();
            Set<String> set = map.keySet();
            for (String s : set) {
                sb.append(s + "=" + map.get(s));
                sb.append("&");
            }
        }
        if (sb != null) {
            String pramas = sb.toString().substring(0, sb.length() - 1);
            //地址自身没有带参数
            if (url.lastIndexOf("?") == -1) {
                url = url + "?" + pramas;
            } else {//地址自身带有参数
                url = url + "&" + pramas;
            }
        }
        return url;
    }

    public static void main(String[] args) {
        try {
            HttpUtils.doGet("http://175.6.40.19:11da/jenkins/job/jenkins_demo_docker-0.0.1-SNAPSHOT/1/consoleText");
        } catch (Exception e) {
            System.out.println("----" + e.getMessage());
        }
    }
}
